<template>
  <div class="content">
    <div id="imageMap"></div>
    <el-select
      v-model="pic"
      class="selectInfo"
      placeholder="Select"
      size="large"
      @change="changeSelete"
    >
      <el-option
        v-for="item of options"
        :key="item.id"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    <popup-list
      ref="dialogLayer"
      @close="close"
      @confirm="confirm"
      v-if="mapViews.isDialog"
    ></popup-list>
  </div>
</template>

<script setup>
import { onMounted, reactive, ref, nextTick, getCurrentInstance } from 'vue'
import 'leaflet/dist/leaflet.css'
import 'leaflet/dist/leaflet'
import * as L from 'leaflet'

import 'leaflet.pm' // Leaflet地图插件, 实现创建和编辑几何图形(点、线、面、圆等)
import 'leaflet.pm/dist/leaflet.pm.css'

import PopupList from './components/popupList.vue'
// 获取当前组件实例
const { proxy } = getCurrentInstance();  //  方式二，此方法在开发环境以及生产环境下都能放到组件上下文对象（推荐）

onMounted(async () => {
  initMap() // 地图初始化
  createLeafletPm() // 创建leaflet.pm
})

// select相关
let pic = ref(0)
const options = [
  {
    id: 0,
    points: [],
    value: 0,
    label: '楼层1',
  },
  {
    id: 1,
    points: [],
    value: 1,
    label: '楼层2',
  },
  {
    id: 2,
    points: [],
    value: 2,
    label: '楼层3',
  }
]
// 点击selete触发
let changeSelete = (e) => {
  // console.log('点击selete触发', e)
  pic.value = e
  initDate() // 平面初始化，引入图层
}

// 地图相关数据
let mapViews = reactive({
  map: null,
  fillColor: '#2d75ff80',
  bounds: [
    [0, 0],
    [0, 0],
  ], // 平面图大小, 定义图像加载的边界值（即在地图上的大小、位置）
  rectangleGeoJson: {},
  rectangleLayer: {},
  imageOverlay: null, // 图片层
  newLayerGroup: null, // 新建图层
  isDialog: false, // 是否显示弹窗
  dialogTarget: '', // 弹窗dom
  LPopup: null, // 弹窗
})

var corner1 = L.latLng(40.712, -74.227); //设置左上角经纬度
var corner2 = L.latLng(40.774, -74.125);	//设置右下点经纬度
var bounds = L.latLngBounds(corner1, corner2); //构建视图限制范

// 地图初始化
let initMap = () => {
  mapViews.map = L.map('imageMap', {
    zoom: 5,
    minZoom: -3,
    maxZoom: 10,
    zoomSnap: 0.1, // 缩放步长，以0.1一级缩放，默认是1一级缩放
    attributionControl: false, // 右下角图例控件false影藏，true显示
    zoomControl: true, // 缩放控件
    crs: L.CRS.Simple, // 坐标系----适用于平面图片的映射
    center: [0,0], //中心坐标
  })
  // 自定义地址icon
  const DefaultIcon = L.icon({
    iconUrl: 'https://5b0988e595225.cdn.sohucs.com/images/20190113/7fe41a44233e4891b63dbfaa3c06041c.png', // icon
    iconSize: '40',
    // shadowUrl: iconShadow // 图标阴影图像的URL。如果不指定，将不会创建阴影图像。
  })
  L.Marker.prototype.options.icon = DefaultIcon
  // configImg() // 平面初始化，引入图层
  initDate() // 平面初始化，引入图层
  // 窗口缩放, 地图自适应缩放
  window.onresize = () => {
    mapViews.map.invalidateSize(true)
    mapViews.map.fitBounds(mapViews.bounds)
  }
}
// 配置底图
let configImg = () => {
  // 配置底图，地图底层数据
  const baseLayer = {
    amap: L.tileLayer(
      "https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
      { attribution: "高德" }
    ),
    ArcGIS: L.tileLayer(
      "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.png",
      { attribution: "ArcGIS卫星影像" }
    ),
    whiteMap: L.tileLayer("http://10.87.211.254:8099/title/{z}/{x}/{y}.png", {
      attribution: "白色底图",
    }),
    tianditu: L.tileLayer(
      "http://t3.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d",
      { attribution: "天地图" }
    ),
    tiandituStreet: L.tileLayer(
      "http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d",
      { attribution: "天地图" }
    ),
  };
  // 配置底图布局
  baseLayer.amap.addTo(mapViews.map);
  // 地图底层控制（控件组）
  L.control
    .layers(
      baseLayer,
      {},
      {
        position: "topright",
      }
    )
    .addTo(mapViews.map);

    createLeafletPm() // 启动leaflet.pm 几何图形的编辑
  
}
// 平面初始化，引入图层
let initDate = () => {
  // 这段是为了切换的时候把上一个平面图中所有图层全删掉,防止携带到下一个平面图中
  // 循环遍历图层删除
  mapViews.map.eachLayer(layer => {
    // 这里面的layer是所有的图层,包括地图本身和平面图本身
    // 可以根据layer里面的某个属性来区分要删除哪些图层
    // 有_latlngs字段的表示矩形图层和多边形图层,有_latlng字段的则表示点,文字图层
    if (layer._latlngs != null || layer._latlng != null) {
      layer.remove() // 删除图层
      // mapViews.map.removeLayer(layer) 这个也可以
    }
  })

  // 获取图片宽高,防止不同尺寸的图片回显在页面上有多余的留白问题
  let img = new Image()
  // select切换时,获取v-model绑定的id,动态更新平面图
  let url = require(`./${pic.value}.jpg`)
  img.src = url
  img.onload = () => {
    let w = img.width
    let h = img.height
    mapViews.bounds = [
      [0, 0],
      [h, w],
    ] // 平面图大小, 定义图像加载的边界值（即在地图上的大小、位置）

    // imageOverlay有值代表已经绘制过地图和平面图,切换平面图就换换url和尺寸就可以了
    // else 没值,就初始化加载一遍平面图到地图中.
    // 添加图片,更换图片
    if (mapViews.imageOverlay) {
      mapViews.imageOverlay.setUrl(url)
      // mapViews.imageOverlay.setBounds(mapViews.bounds)
    } else {
      // 新建图层
      mapViews.imageOverlay = L.imageOverlay(url, mapViews.bounds).addTo(mapViews.map)
      // 设置地图图层区域
      mapViews.map.fitBounds(mapViews.bounds)
    }
  }

  mapViews.newLayerGroup = L.layerGroup().addTo(mapViews.map); // 创建你的图层组, 用于保存点位

  // 获取本地存储的图层数据
  let res = JSON.parse(localStorage.getItem('layers')) || []
  // 当前平面图下如果有绘制的图层,就进行回显
  if (res[pic.value]) {
    // console.log('res[pic.value]', res[pic.value])
    // 循环绘制图层
    res[pic.value].forEach((e) => {
      if (e.latlngs) {
        var lay = L.polygon(e.latlngs, {

        }).addTo(mapViews.map).on('pm:edit', editLayClick()).on('click', layClick()).on('pm:dragend', dragendLayClick)
        // 这个id每次刷新,来回切换平面图,都会改变,所以要更新一下,如果不更新,下面删除,拖拽,编辑,的时候就找不到图层了
        e._leaflet_id = lay._leaflet_id
      }

    })
    localStorage.setItem('layers', JSON.stringify(res))
  }
}
// 创建leaflet.pm
let createLeafletPm = () => {
  // 绘图工具
  mapViews.map.pm.setLang('zh') // 控件提示设置中文
  mapViews.map.pm.addControls({
    position: 'topleft', // 控件菜单位置
    drawPolygon: true, //绘制多边形
    drawMarker: true, //绘制标记点
    drawCircleMarker: true, //绘制圆形标记
    drawPolyline: true, //绘制线条
    drawRectangle: true, //绘制矩形
    drawCircle: true, //绘制圆圈
    editMode: true, //编辑多边形
    dragMode: true, //拖动多边形
    cutPolygon: true, //添加⼀个按钮以删除多边形⾥⾯的部分内容
    removalMode: true, //清除多边形
    allowLayerGroup: [mapViews.newLayerGroup] // 只允许在yourLayerGroup内绘制
  })

  // 全局图层样式
  mapViews.map.pm.setPathOptions({
    color: 'orange',
    fillColor: 'green',
    fillOpacity: 0.4,
    snappable: true, //启⽤捕捉到其他绘制图形的顶点
    snapDistance: 20, //顶点捕捉距离
  })
  // 启用多边形绘图模式
  const options = {
    // 连接线标记之间的线
    templineStyle: {
      color: "red",
    },
    // 提⽰线从最后⼀个标记到⿏标光标的线
    hintlineStyle: {
      color: "red",
      dashArray: [5, 5],
    },
    // 绘制完成的样式
    pathOptions: {
      color: "orange",
      fillColor: "green",
    },
  };
  // 激活绘制多边形功能-1、单独设置某个模式的样式
  mapViews.map.pm.enableDraw("Polygon", options);
  // 关闭绘制--注意也可以关闭其他模式的绘制功能
  mapViews.map.pm.disableDraw("Polygon");
  // 启用形状的绘图模式:线  (点:Marker, 圆点:CircleMarker, 圆:Circle, 线:Line, 矩形:Rectangle, 多边形: Polygon, 切割:Cut)
  // mapViews.map.pm.enableDraw("Marker");


  // 给地图绑定绘制、删除的事件
  mapViews.map.on('pm:create', createClick)
  mapViews.map.on('pm:remove', removeClick)
  // 设置地图点击事件监听，用于禁止在禁绘区域绘图

  // 禁止--disable(), 允许--enable()
  // 禁止背景图拖拽,默认是可拖拽的
  mapViews.map.dragging.disable()
  // 禁止双击缩放,默认是可双击缩放的
  mapViews.map.doubleClickZoom.disable()
  // 禁止滚动缩放,默认是可滚动缩放的
  // mapViews.map.scrollWheelZoom.disable()
  // 禁止拖动（拖动标记--仅在maker状态下可用）
  mapViews.map.dragging.enable();
}

// 图层绘制完成
let createClick = (e) => {
  // console.log('图层绘制完成', e)
  // 获取缓存的图层数据,看看之前有没有绘制过,本次绘制完push到改集合中
  let res = JSON.parse(localStorage.getItem('layers')) || []
  // 没有值没有绘制,赋个值初始值
  if (!res[pic.value]) res[pic.value] = []
  // 只要两个参数即可保存该图层信息,id和经纬度
  let obj = {
    _leaflet_id: e.layer._leaflet_id,
    latlngs: e.layer._latlngs,
  }
  res[pic.value].push(obj)
  localStorage.setItem('layers', JSON.stringify(res))

  // 设置图层样式
  // e.layer.setStyle({
  //   fillOpacity: 0.5, // 内部填充透明度
  //   fillColor: mapViews.fillColor, // 内部填充颜色，如不设置，默认为color颜色
  //   color: 'red', // 线段颜色
  //   // weight：线段宽度
  //   // opacity：线段透明度
  //   // dashArray：虚线间隔
  //   // fill：是否填充内部(true/false)
  //   // fillColor:内部填充颜色，如不设置，默认为color颜色
  //   // fillOpacity：内部填充透明度
  // })
  // 给图层绑定点击、拖拽、编辑事件
  e.layer.on('pm:edit', editLayClick).on('click', layClick).on('pm:dragend', dragendLayClick).on("pm:globalremovalmodetoggled", removeLayClick)
  // 弹窗，图层绘制完自动弹窗 参数:(当前图层的layer, 当前图层的中心点的坐标)
  console.log('e.layer.getBounds().getCenter()', e.layer.getBounds().getCenter(), e.layer)
  dialog(e.layer, e.layer.getBounds().getCenter())
}
// 区域图层点击
let layClick = (e) => {
  // console.log('区域图层点击', e)
  // 弹窗, 参数:(当前点击的图层的layer, 点击的坐标)
  if (e) {
    dialog(e.target, e.latlng)
  }
}
const dialogLayer = ref(null) // 定义ref
// 弹窗事件
let dialog = (target, latlng) => {
  mapViews.dialogTarget = target // 主要是在弹窗组件中用到
  mapViews.isDialog = true
  nextTick(() => {
    mapViews.LPopup = L.popup({ closeOnClick: false, closeButton: false }).setLatLng(latlng).setContent(dialogLayer.value.popupList).openOn(mapViews.map)
    // 修复点击popup模态框时，select下拉列表不消失问题
    let dom = document.getElementsByClassName('leaflet-popup-content-wrapper')[0]
    dom.onclick = function () {
      // dialogLayer.$refs.selectRef.visible = false
    }
  })
}
// 图层删除
let removeClick = (e) => {
  // console.log('图层删除', e)
  let res = JSON.parse(localStorage.getItem('layers')) || []
  res[pic.value].forEach((d, i) => {
    if (d._leaflet_id == e.layer._leaflet_id) {
      res[pic.value].splice(i, 1)
    }
  })
  localStorage.setItem('layers', JSON.stringify(res))
}
// 区域图层拖拽
let dragendLayClick = (e) => {
  // console.log('区域图层拖拽', e)
}
// 区域图层编辑
let editLayClick = (e) => {
  // console.log('图层编辑', e)
  let res = JSON.parse(localStorage.getItem('layers'))
  if (res) {
    // 循环遍历更新一下id和经纬度就可以了
    // res[pic.value].forEach((d) => {
    //   if(e.target._leaflet_id) {
    //     if (d._leaflet_id == e.target._leaflet_id) {
    //     d.latlngs = e.target._latlngs
    //     d._leaflet_id = e.target._leaflet_id
    //   }
    //   }
    // })
    localStorage.setItem('layers', JSON.stringify(res))
  }
}
// 清除图层时
let removeLayClick = (e) => {
  // console.log('清除图层时调用', e)
}
// 移除图层
let deleteDrawRectangle = (e) => {
  // console.log('移除图层', e)
  mapViews.map.pm.toggleGlobalRemovalMode();
  // mapViews.map.removeLayer(mapViews.rectangleLayer)
}

let close = () => {
  console.log('古纳比')
}
let confirm = () => {
  console.log('确认')
  mapViews.LPopup.close()
}

</script>

<style lang="scss">
/* style语法糖--------------------:class="$style.txt"*/
.content {
  display: flex;
  justify-content: space-around;
}

#imageMap {
  width: 80%;
  height: 600px;
}
.selectInfo {
  width: 15%;
}
</style>
